package cn.mumzone.pos.ui.widgets.keyboard;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.Keyboard.Key;
import android.inputmethodservice.KeyboardView;
import android.support.annotation.NonNull;
import android.text.Editable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.widget.EditText;

import java.lang.reflect.Field;
import java.util.List;

import cn.mumzone.basic.util.CommonUtils;
import cn.mumzone.basic.util.PosToast;
import cn.mumzone.pos.R;

public class PosKeyBoardView extends KeyboardView {

    private Context mContext;
    private Keyboard mKeyBoard;
    private EditText mTargetEditText;

    private Drawable mDoneNormalBg = getResources().getDrawable(R.drawable.shape_bg_key_done_normal);
    private Drawable mDoneUnavailableBg = getResources().getDrawable(R.drawable.shape_bg_key_done_not_available);

    private int mPressedKeyCode = Integer.MAX_VALUE;
    private int mCurrKeyTextColor;
    private int mDeleteKeyIconDrawable = R.drawable.svg_ic_delete;

    private int mTargetEditTextId;
    private double mTargetEditTextMaxValue;
    private String mOverMsg;

    private boolean mIsDotAvailable = true;
    private boolean mIsCheckMaxValue = false;
    private String mKeyDoneText = "确认";

    public PosKeyBoardView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;

        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.PosKeyBoardView);

        mTargetEditTextId = ta.getResourceId(R.styleable.PosKeyBoardView_target_view_id, 0);
        mIsDotAvailable = ta.getBoolean(R.styleable.PosKeyBoardView_is_dot_available, true);

        Drawable doneBgDrawable = ta.getDrawable(R.styleable.PosKeyBoardView_done_key_background);
        if (doneBgDrawable != null) {
            mDoneNormalBg = doneBgDrawable;
        }

        Drawable doneNotEnableBgDrawable = ta.getDrawable(R.styleable.PosKeyBoardView_done_key_background_not_enable);
        if (doneNotEnableBgDrawable != null) {
            mDoneUnavailableBg = doneNotEnableBgDrawable;
        }

        String doneKeyText = ta.getString(R.styleable.PosKeyBoardView_done_key_text);
        if (!TextUtils.isEmpty(doneKeyText)) {
            mKeyDoneText = doneKeyText;
        }

        ta.recycle();

        setPreviewEnabled(false);
        setKeyboard(new Keyboard(mContext, R.xml.keyboard_number));
        setOnKeyboardActionListener(mOnKeyboardActionListener);

    }

    /**
     * 重新画一些按键
     */
    @Override
    public void onDraw(Canvas canvas) {

        super.onDraw(canvas);

        mKeyBoard = this.getKeyboard();
        List<Key> keys = null;
        if (mKeyBoard != null) {
            keys = mKeyBoard.getKeys();
        }

        Drawable mDoneKeyBackground;

        // mTargetEditText 一般会有默认文本，有默认文本时就可以点击确认按钮
        if (mTargetEditText != null && !TextUtils.isEmpty(mTargetEditText.getText().toString())) {
            mDoneKeyBackground = mDoneNormalBg;
        } else {
            mDoneKeyBackground = mDoneUnavailableBg;
        }

        if (keys != null) {
            for (Key key : keys) {

                // 小数点不可用时，绘制其颜色为透明
                if (!mIsDotAvailable && key.codes[0] == 46) {

                    Field keyBgDrawable = null;
                    try {
                        keyBgDrawable = KeyboardView.class.getDeclaredField("mKeyBackground");
                        keyBgDrawable.setAccessible(true);

                    drawKeyBackground((Drawable) keyBgDrawable.get(this), canvas, key);
                    key.label = "";
                    drawText(canvas, key, R.color.transparent);

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

                // 改变当前点击的按键文字颜色
                if (key.codes[0] == mPressedKeyCode) {
                    drawText(canvas, key, mCurrKeyTextColor);
                }

                // 改变当前删除按钮的图片颜色，点击时为白色，松开后为黑色
                // 但是松手后 mPressedKeyCode 会重置，所以需要单独处理删除按钮
                if (key.codes[0] == Keyboard.KEYCODE_DELETE) {
                    key.icon = getResources().getDrawable(mDeleteKeyIconDrawable);
                    drawText(canvas, key, mCurrKeyTextColor);
                }

                // 根据 EditText 是否有内容，实时更新 Keyboard 的确认按钮
                if (key.codes[0] == Keyboard.KEYCODE_DONE) {
                    drawKeyBackground(mDoneKeyBackground, canvas, key);
                    key.label = mKeyDoneText;
                    drawText(canvas, key, Color.WHITE);
                }

            }
        }
    }

    private void drawKeyBackground(Drawable drawable, Canvas canvas, Key key) {
        int[] drawableState = key.getCurrentDrawableState();
        if (key.codes[0] != 0) {
            drawable.setState(drawableState);
        }
        drawable.setBounds(key.x, key.y, key.x + key.width, key.y
                + key.height);
        drawable.draw(canvas);
    }

    private void drawText(Canvas canvas, Key key, int color) {
        Rect bounds = new Rect();
        Paint paint = new Paint();
        paint.setTextAlign(Paint.Align.CENTER);

        paint.setAntiAlias(true);

        paint.setColor(color);

        if (key.label != null) {
            String label = key.label.toString();

            Field field;

            if (label.length() > 1 && key.codes.length < 2) {
                int labelTextSize = 0;
                try {
                    field = KeyboardView.class.getDeclaredField("mLabelTextSize");
                    field.setAccessible(true);
                    labelTextSize = (int) field.get(this);
                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                paint.setTextSize(labelTextSize);
                paint.setTypeface(Typeface.DEFAULT_BOLD);
            } else {
                int keyTextSize = 0;
                try {
                    field = KeyboardView.class.getDeclaredField("mKeyTextSize");
                    field.setAccessible(true);
                    keyTextSize = (int) field.get(this);
                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                paint.setTextSize(keyTextSize);
                paint.setTypeface(Typeface.DEFAULT);
            }

            paint.getTextBounds(key.label.toString(), 0, key.label.toString()
                    .length(), bounds);
            canvas.drawText(key.label.toString(), key.x + (key.width / 2),
                    (key.y + key.height / 2) + (paint.getTextSize() - paint.descent()) / 2, paint);
        } else if (key.icon != null) {
            key.icon.setBounds(key.x + (key.width - key.icon.getIntrinsicWidth()) / 2, key.y + (key.height - key.icon.getIntrinsicHeight()) / 2,
                    key.x + (key.width - key.icon.getIntrinsicWidth()) / 2 + key.icon.getIntrinsicWidth(), key.y + (key.height - key.icon.getIntrinsicHeight()) / 2 + key.icon.getIntrinsicHeight());
            key.icon.draw(canvas);
        }

    }

    private KeyboardView.OnKeyboardActionListener mOnKeyboardActionListener = new KeyboardView.OnKeyboardActionListener() {
        @Override
        public void onPress(int primaryCode) {

            // 不处理确认按钮的 onPress 事件，其状态由 EditText 的输入状态决定
            if (primaryCode == Keyboard.KEYCODE_DONE) {
                return;
            }

            // 小数点不可用
            if (!mIsDotAvailable && primaryCode == 46) {
                return;
            }

            // 实时更新删除按钮，按下为白色，松开为黑色
            if (primaryCode == Keyboard.KEYCODE_DELETE) {
                mDeleteKeyIconDrawable = R.drawable.svg_ic_delete_pressed;
            }

            mPressedKeyCode = primaryCode;
            mCurrKeyTextColor = Color.WHITE;
            invalidate();
        }

        @Override
        public void onRelease(int primaryCode) {

            // 小数点不可用
            if (!mIsDotAvailable && primaryCode == 46) {
                return;
            }

            mPressedKeyCode = Integer.MAX_VALUE;
            mDeleteKeyIconDrawable = R.drawable.svg_ic_delete;
            invalidate();
        }

        @Override
        public void onKey(int primaryCode, int[] keyCodes) {

            if (mTargetEditText == null) {
                ViewGroup parentView = (ViewGroup) PosKeyBoardView.this.getParent();
                mTargetEditText = parentView.findViewById(mTargetEditTextId);
            }

            Editable editable = mTargetEditText.getText();
            int start = mTargetEditText.getSelectionStart();
            int end = mTargetEditText.getSelectionEnd();


            if (primaryCode == Keyboard.KEYCODE_DELETE) { // 删除
                if (editable != null && editable.length() > 0) {
                    if (start > 0) {
                        editable.delete(start - 1, start);
                    }
                }
            } else if (primaryCode == Keyboard.KEYCODE_CANCEL) { // 重新输入
                if (editable != null && editable.length() > 0) {
//                    if (start > 0) {
                    editable.delete(0, editable.length());
//                        mTargetEditText.setText("");
//                    }
                }

            } else if (primaryCode == Keyboard.KEYCODE_DONE) { // 确认

                // EditText 为空时，不允许点击
                if (mTargetEditText != null && TextUtils.isEmpty(mTargetEditText.getText().toString())) {
                    return;
                }

                if (mIsCheckMaxValue) {
                    // 超过最大值时提示
                    if (Double.parseDouble(mTargetEditText.getText().toString()) > mTargetEditTextMaxValue) {

                        if (!TextUtils.isEmpty(mOverMsg)) {
                            PosToast.INSTANCE.makeShortToast(mContext, mOverMsg);
                        }
                        return;
                    }

                }

                if (onConfirmClickListener != null)
                    onConfirmClickListener.onConfirmClick(mTargetEditText.getText().toString());

            } else {
                if (!mIsDotAvailable && primaryCode == 46) { // 小数点不可用
                    return;
                }

                editable.replace(start, end, Character.toString((char) primaryCode));
                mTargetEditText.setSelection(editable.length());
            }
        }

        @Override
        public void onText(CharSequence text) {

        }

        @Override
        public void swipeLeft() {

        }

        @Override
        public void swipeRight() {

        }

        @Override
        public void swipeDown() {

        }

        @Override
        public void swipeUp() {

        }
    };

    public double getMaxValue() {
        return mTargetEditTextMaxValue;
    }

    public void setMaxValue(double mMaxValue) {
        this.mTargetEditTextMaxValue = mMaxValue;
    }

    private OnConfirmClickListener onConfirmClickListener;

    public void setOnConfirmClickListener(OnConfirmClickListener onConfirmClickListener) {
        this.onConfirmClickListener = onConfirmClickListener;
    }

    public interface OnConfirmClickListener {

        void onConfirmClick(String text);
    }


    public void attachTo(EditText editText) {
        if (editText == null) {
            throw new RuntimeException("PosKeyboard must attach to a EditText View");
        }
        this.mTargetEditText = editText;
        CommonUtils.hideKeyboard(mContext, editText);
    }

    public void attachTo(EditText editText, double maxValue, String overMsg) {
        if (editText == null) {
            throw new RuntimeException("PosKeyboard must attach to a EditText View");
        }
        this.mTargetEditText = editText;
        this.mTargetEditTextMaxValue = maxValue;
        this.mOverMsg = overMsg;
        this.mIsCheckMaxValue = true;
        CommonUtils.hideKeyboard(mContext, editText);
    }

}
